/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI;

import MouseSensorDriver.SaveLoadExp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

/**
 *
 * @author Asko
 */
public class EndoscopeExpContainer implements TableModel, SaveLoadExp {

    ArrayList<EndoscopExp> exps = new ArrayList<>();
    ArrayList<TableModelListener> tml = new ArrayList<>();
    private int columnCnt = 26;
    private final int MAX_DIGS_CNT = 3;
    private final int MIN_DIGS_CNT = 0;
    String delim = "; ";
    StringTokenizer tokenizer;
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    FileOutputStream fos = null;
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    NumberFormat nform = NumberFormat.getInstance();

    public EndoscopeExpContainer() {
        nform.setMaximumFractionDigits(MAX_DIGS_CNT);
        nform.setMinimumFractionDigits(MIN_DIGS_CNT);
    }

    public void add(EndoscopExp ch) {
        exps.add(ch);
        changed();
    }

    public EndoscopExp get(int chNum) {
        return exps.get(chNum);
    }

    public void remove(int chNum) {
        exps.remove(chNum);
        changed();
    }

    public void remove(Experiment obj) {
        exps.remove(obj);
        changed();
    }

    public void removeAll() {
        exps.clear();
        changed();
    }

    public int size() {
        return exps.size();
    }

    private void changed() {
        for (int i = 0; i < tml.size(); i++) {
            tml.get(i).tableChanged(new TableModelEvent(this));
        }
    }

    @Override
    public int getRowCount() {
        return size();
    }

    @Override
    public int getColumnCount() {
        return columnCnt;
    }

    @Override
    public String getColumnName(int columnIndex) {
        switch (columnIndex) {

            case 0: {
                return "#";
            }
            case 1: {
                return "Единицы измерения";
            }
            case 2: {
                return "Начальная позиция";
            }
            case 3: {
                return "Начальная позиция двигателя (ед.)";
            }

            case 4: {
                return "Начальная позиция АЦП (ед.)";
            }

            case 5: {
                return "Начальный момент даигателя (е.д.) ";
            }
            case 6: {
                return "Начальный момент АЦП (е.д.) ";
            }
            case 7: {
                return "Конечная позиция";
            }
            case 8: {
                return "Конечная позиция двигателя(ед.)";
            }
            case 9: {
                return "Конечная позиция АЦП(ед.)";
            }

            case 10: {
                return "Конечный момент двигателя(ед.)";
            }
            case 11: {
                return "Конечный момент АЦП(ед.)";
            }

            case 12: {
                return "Разница заданных позиций (ед.)";
            }
            case 13: {
                return "Разница позиций двигателя (ед.)";
            }
            case 14: {
                return "Разница позиций АЦП (ед.)";
            }
            case 15: {
                return "Разница моментов двигателя (ед.)";
            }

            case 16: {
                return "Разница моментов АЦП (ед.)";
            }
            case 17: {
                return "Абсолютная погрешность перемещений(ед.)";
            }
            case 18: {
                return "Относительная погрешность перемещений ";
            }
            case 19: {
                return "СКО (перемещения)";
            }
            case 20: {
                return "Макс. отклонение(перемещения)";
            }

            case 21 : {
                  return "Абсолютная погрешность сил";
             }
            case 22: {
                return "Относительная погрешность сил";
            }
            case 23: {
                return "CKO (силы)";

            }
            case 24: {
                return "Макc. отклонение(силы)";
            }
            case 25: {
                return "Время реакции манипулятора";
            }    
            default:
                return "";
        }


            //            case 0: {
//                return "#";
//            }
//            case 1: {
//                return "Единицы измерения";
//            }
//            case 2: {
//                return "Начальная позиция";
//            }
//            case 3: {
//                return "Начальная позиция двигателя (ед.)";
//            }
//            case 4: {
//                return "Начальная позиция АЦП (ед.)";
//            }
//            case 5: {
//                return "Конечная позиция";
//            }
//            case 6: {
//                return "Конечная позиция двигателя(ед.)";
//            }
//            case 7: {
//                return "Конечная позиция АЦП(ед.)";
//            }
//            case 8: {
//                return "Разница заданных позиций (ед.)";
//            }
//            case 9: {
//                return "Разница  позиций двигателя (ед.)";
//            }
//            case 10: {
//                return "Разница  позиций АЦП (ед.)";
//            }
//            case 11: {
//                return "Абсолютная погрешность (ед.)";
//            }
//            case 12: {
//                return "Относительная погрешность";
//            }
//            case 13: {
//                return "СКО";
//            }
//            case 14: {
//                return "Макс. отклонение ";
//            }
//            default:
//                return "";
//        }
        
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        switch (columnIndex) {


//                     case 0: {
//                return "" + (rowIndex + 1);
//            }
//            case 1: {
//                return exps.get(rowIndex).getChannel().getGear().getUnitPosition()
//                        + ", " + exps.get(rowIndex)
//                        .getChannel().getGear().getUnitTorque();
//            }
//            case 2: {
//                return "" + exps.get(rowIndex).getStPos();
//            }
//            case 3: {
//                return "" + exps.get(rowIndex).getStPos_eng();
//            }
//            case 4: {
//                return "" + exps.get(rowIndex).getSrcStPos_eng();
//            }
//            case 5: {
//                return "" + exps.get(rowIndex).getStPos_adc();
//            }
//            case 6: {
//                return "" + exps.get(rowIndex).getSrcStPos_adc();
//            }
//            case 7: {
//                return "" + exps.get(rowIndex).getStTor_eng();
//            }
//            case 8: {
//                return "" + exps.get(rowIndex).getSrcStTor_eng();
//            }
//            case 9: {
//                return "" + exps.get(rowIndex).getStTor_adc();
//            }
//            case 10: {
//                return "" + exps.get(rowIndex).getSrcStTor_adc();
//            }
//            case 11: {
//                return "" + exps.get(rowIndex).getEndPos();
//            }
//            case 12: {
//                return "" + exps.get(rowIndex).getEndPos_eng();
//            }
//            case 13: {
//                return "" + exps.get(rowIndex).getSrcEndPos_eng();
//            }
//            case 14: {
//               /* if (exps.get(rowIndex).getChannel().gear.getActuator().getEngineId()==4) {
//                double real = exps.get(rowIndex).getEndPos_adc();
//                double endVal = exps.get(rowIndex).getEndPos();
//                if (endVal < 31) {
//                    return "" + real * 2.1;
//                }
//
//                if (endVal < 75 && endVal > 31) {
//                    return "" + real * (endVal * -0.027638680666666665
//                            + 2.9882993);
//                }
//                if (endVal >= 75) {
//                    return "" + real * (endVal * -0.0029303273561904772
//                            + 1.3326582049047622);
//                }  
//                }
//                else {*/
//                    return "" + exps.get(rowIndex).getEndPos_adc();
//            }
//            case 15: {
//                return "" + exps.get(rowIndex).getSrcStPos_adc();
//            }
//            case 16: {
//                return "" + exps.get(rowIndex).getEndTor_eng();
//            }
//            case 17: {
//                return "" + exps.get(rowIndex).getSrcEndTor_eng();
//            }
//            case 18: {
//                return "" + exps.get(rowIndex).getEndTor_adc();
//            }
//            case 19: {
//                return "" + exps.get(rowIndex).getSrcStTor_adc();
//            }
//            case 20: {
//                return "" + (exps.get(rowIndex).getEndPos()
//                        - exps.get(rowIndex).getStPos());
//            }
//            case 21: {
//                return "" + (exps.get(rowIndex).getEndPos_eng()
//                        - exps.get(rowIndex).getStPos_eng());
//            }
//            case 22: {
//                return "" + (exps.get(rowIndex).getSrcEndPos_eng()
//                        - exps.get(rowIndex).getSrcStPos_eng());
//            }
//            case 23: {
//                return "" + (exps.get(rowIndex).getEndPos_adc()
//                        - exps.get(rowIndex).getStPos_adc());
//            }
//            case 24: {
//                return "" + (exps.get(rowIndex).getSrcEndPos_adc()
//                        - exps.get(rowIndex).getSrcEndPos_adc());
//            }
//            case 25: {
//                return "" + (exps.get(rowIndex).getEndTor_eng()
//                        - exps.get(rowIndex).getStTor_eng());
//            }
//            case 26: {
//                return "" + (exps.get(rowIndex).getSrcEndTor_eng()
//                        - exps.get(rowIndex).getSrcStTor_eng());
//            }
//            case 27: {
//                return "" + (exps.get(rowIndex).getEndTor_adc()
//                        - exps.get(rowIndex).getStTor_adc());
//            }
//            case 28: {
//                return "" + (exps.get(rowIndex).getSrcEndTor_adc()
//                        - exps.get(rowIndex).getSrcEndTor_adc());
//            }

            //Момент двигателя

            //Конечный момент двигателя
//             case 16: {
//                return "" + exps.get(rowIndex).getEndTor_eng();
//            }
//            Конечный момент АЦП 
//            case 18: {
//                return "" + exps.get(rowIndex).getEndTor_adc();
//            }
            //Разница моментов двигателей
//              case 15: {
//                return "" + (exps.get(rowIndex).getEndTor_eng()
//                        - exps.get(rowIndex).getStTor_eng());
//            }
//            case 16: {
//                return "" + (exps.get(rowIndex).getEndTor_adc()
//                        - exps.get(rowIndex).getStTor_adc());
//            }





            case 0: {
                return "" + (rowIndex + 1);
            }
            case 1: {
                return "" + exps.get(rowIndex).getChannel().getGear().getUnitPosition()
                        + ", " + exps.get(rowIndex)
                        .getChannel().getGear().getUnitTorque();
            }
            case 2: {
                return "" + nform.format(exps.get(rowIndex).getStPos());
            }
            case 3: {
                return "" + nform.format(exps.get(rowIndex).getStPos_eng());
            }
            case 4: {
                return "" + nform.format(exps.get(rowIndex).getStPos_adc());
            }
            case 5: {
                return "" + nform.format(exps.get(rowIndex).getStTor_eng());
            }
            case 6: {
                return "" + nform.format(exps.get(rowIndex).getStTor_adc());
            }
            case 7: {
                return "" + nform.format(exps.get(rowIndex).getEndPos());
            }

            case 8: {
                return "" + nform.format(exps.get(rowIndex).getEndPos_eng());
            }
            case 9: {
                return "" + nform.format(exps.get(rowIndex).getEndPos_adc());
            }

            case 10: {
                return "" + nform.format(exps.get(rowIndex).getEndTor_eng());
            }
            case 11: {
                return "" + nform.format(exps.get(rowIndex).getEndTor_adc());
            }


            case 12: {
                return "" + nform.format((exps.get(rowIndex).getEndPos()
                        - exps.get(rowIndex).getStPos()));
            }
            case 13: {
                return "" + nform.format((exps.get(rowIndex).getEndPos_eng()
                        - exps.get(rowIndex).getStPos_eng()));
            }
            case 14: {
                return "" + nform.format((exps.get(rowIndex).getEndPos_adc()
                        - exps.get(rowIndex).getStPos_adc()));
            }
            case 15: {
                return "" + nform.format((exps.get(rowIndex).getEndTor_eng()
                        - exps.get(rowIndex).getStTor_eng()));
            }
            case 16: {
                return "" + nform.format((exps.get(rowIndex).getEndTor_adc()
                        - exps.get(rowIndex).getStTor_adc()));
            }

            case 17: {
                return "" + nform.format(exps.get(rowIndex).getAbsError());
            }
            case 18: {
                return "" + nform.format(exps.get(rowIndex).getRelError());
            }
            case 19: {
                double sko = exps.get(rowIndex).getSigma();
                if (sko == -1) {
                    return "none";
                } else {
                    return nform.format(sko);
                }
            }
            case 20: {
                double maxe = exps.get(rowIndex).getMaxAbsError();
                if (maxe == -1) {
                    return "none";
                } else {
                    return nform.format(maxe);
                }
            }

            case 21: {
                return "" + nform.format(exps.get(rowIndex).getAbsErrorTorq());
            }

            case 22: {
                return "" + nform.format(exps.get(rowIndex).getRelErrorTorq());
            }

            case 23: {
                double sko = exps.get(rowIndex).getSigmaTor();
                if (sko == -1) {
                    return "none";
                } else {
                    return nform.format(sko);
                }
            }

            case 24: {
                double maxe = exps.get(rowIndex).getMaxAbsErrorTor();
                if (maxe == -1) {
                    return "none";
                } else {
                    return nform.format(maxe);
                }
            }
                
            case 25: {
                return nform.format(exps.get(rowIndex).getMeasuredTime());
            }    
            default:
                return "";
        }
    }

    public String getCSV() {
        String buf = "";
        for (int i = 0; i < getColumnCount(); i++) {
            buf += getColumnName(i) + ";";
        }
        buf += "\n";
        for (int i = 0; i < getRowCount(); i++) {
            for (int j = 0; j < getColumnCount(); j++) {
                buf += getValueAt(i, j).toString() + ";";
            }
            buf += "\n";
        }
        buf = buf.replace('.', ',');
        return buf;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    }

    @Override
    public void addTableModelListener(TableModelListener l) {
        tml.add(l);
    }

    @Override
    public void removeTableModelListener(TableModelListener l) {
        tml.remove(l);
    }

    public double getSigma() {
        if (exps.size() > 0) {
            double sum = 0;
            for (int i = 0; i < exps.size(); i++) {
                sum += (Math.pow(exps.get(i).getAbsError(), 2)) / exps.size();
            }
            return Math.sqrt(sum);
        } else {
            return -1;
        }
    }

    public double getMaxAbsError() {
        if (exps.size() > 0) {
            double max = exps.get(0).getAbsError();
            double buf;
            for (int i = 1; i < exps.size(); i++) {
                buf = exps.get(i).getAbsError();
                if (max < buf) {
                    max = buf;
                }
            }
            return max;
        } else {
            return -1;
        }
    }

    public String getValsAfter(double val, int numsCnt) {
        return String.valueOf(val).substring(0, String.valueOf(val).
                indexOf('.') + numsCnt + 1);
    }

    @Override
    public void saveToFile(File file) {
        try {
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            oos = new ObjectOutputStream(bos);
            for (int i = 0; i < exps.size(); i++) {
                oos.writeObject(exps.get(i));
            }
            //    System.out.println("Experiment has been saved to " + file);
            oos.close();
            bos.close();
            fos.close();
        } catch (IOException ex) {
            Logger.getLogger(EndoscopeExpContainer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void loadFromFile(File file) {
        this.removeAll();
        try {
            Object obj;
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            ois = new ObjectInputStream(bis);
            while ((obj = ois.readObject()) != null) {
                this.add((EndoscopExp) obj);
            }
            ois.close();
            bis.close();
            fis.close();
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(EndoscopeExpContainer.class.getName()).
                    log(Level.SEVERE, null, ex);
        } catch (EOFException ex) {
            //      System.err.println("Reaching eof.");
        } catch (IOException ex) {
            Logger.getLogger(EndoscopeExpContainer.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
    }
}
